package com.azier.generator;

import com.azier.kapacitor.util.CollectionUtil;
import com.azier.kapacitor.util.JsonUtil;
import com.azier.kapacitor.util.StringUtil;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 1 * @Author: luoj
 * 2 * @Date: 2019/11/11 17:25
 * 3
 */
public class FreeMarkUtil {
    private static final List<String> node = new ArrayList();

    static {
        node.add("alert_node");
        node.add("barrier_node");
        node.add("change_detect_node");
        node.add("combine_node");
        node.add("default_node");
        node.add("delete_node");
        node.add("derivative_node");
        node.add("ec2_autoscale_node");
        node.add("eval_node");
        node.add("flatten_node");
        node.add("from_node");
        node.add("group_by_node");
        node.add("http_out_node");
        node.add("http_post_node");
        node.add("influx_d_b_out_node");
        node.add("influx_q_l_node");
        node.add("join_node");
        node.add("k8s_autoscale_node");
        node.add("kapacitor_loopback");
        node.add("log_node");
        node.add("no_op_node");
        node.add("query_node");
        node.add("sample_node");
        node.add("shift_node");
        node.add("sideload_node");
        node.add("state_count_node");
        node.add("state_duration_node");
        node.add("stats_node");
        node.add("swarm_autoscale_node");
        node.add("u_d_f_node");
        node.add("union_node");
        node.add("where_node");
        node.add("window_node");
    }



    // 第二种方法
// 这种方法是JAVA自带的URL来抓取网站内容
    public static String getPageContent(String strUrl, String strPostRequest,
                                        int maxLength) {
        // 读取结果网页
        StringBuffer buffer = new StringBuffer();
        System.setProperty("sun.net.client.defaultConnectTimeout", "5000");
        System.setProperty("sun.net.client.defaultReadTimeout", "5000");
        try {
            URL newUrl = new URL(strUrl);
            HttpURLConnection hConnect = (HttpURLConnection) newUrl
                    .openConnection();
            // POST方式的额外数据
            if (strPostRequest.length() > 0) {
                hConnect.setDoOutput(true);
                OutputStreamWriter out = new OutputStreamWriter(hConnect
                        .getOutputStream());
                out.write(strPostRequest);
                out.flush();
                out.close();
            }
            // 读取内容
            BufferedReader rd = new BufferedReader(new InputStreamReader(
                    hConnect.getInputStream()));
            int ch;
            for (int length = 0; (ch = rd.read()) > -1
                    && (maxLength <= 0 || length < maxLength); length++)
                buffer.append((char) ch);
            String s = buffer.toString();
            s.replaceAll("//&[a-zA-Z]{1,10};", "").replaceAll("<[^>]*>", "");
            rd.close();
            hConnect.disconnect();
            return buffer.toString().trim();
        } catch (Exception e) {
            // return "错误:读取网页失败！";
            //
            return null;
        }
    }

    public static void main(String[] args) {
        Map<String,Node> nodeMap = new HashMap<>();
        Map<String,Method> methodMap = new HashMap<>();
        int i = 0;
        for (String nodeName : node) {
            try {
                String url = "https://docs.influxdata.com/kapacitor/v1.5/nodes/"+nodeName+"/";
                Document document = Jsoup.connect(url).get();
                Node node = new Node();
                transConstructor(document,node,nodeMap);
                transMethod(document,node,methodMap);
                linkNode(document,node);
                i ++;
                TimeUnit.SECONDS.sleep(120);
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
        String path = FreeMarkUtil.class.getResource("").getPath();
        System.out.println(path);
        System.out.println("总计："+node.size()+",成功："+i);
        try {
            createJsonFile(JsonUtil.toJson(nodeMap),"nodeMap.json");
            createJsonFile(JsonUtil.toJson(methodMap),"methodMap.json");
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }

    }

    private static void createJsonFile(String json,String name) throws IOException {
        // 保证创建一个新文件
        String path = FreeMarkUtil.class.getResource("").getPath() + name;
        File file = new File(path);
        if (!file.getParentFile().exists()) { // 如果父目录不存在，创建父目录
            file.getParentFile().mkdirs();
        }
        if (file.exists()) { // 如果已存在,删除旧文件
            file.delete();
        }
        file.createNewFile();
        Writer write = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
        write.write(json);
        write.flush();
        write.close();
    }

    private static void getNodeUrl(Document document){
        Element element = document.getElementsByAttributeValue("href","/kapacitor/v1.5/nodes/").first();
        Elements es = element.parent().parent().getElementsByClass("sidebar--page");
        for (Element e : es) {
            System.out.println("node.add(\""+title(e.text())+"\");");
        }
    }
    /**
     * 各单词首字母大写
     */
    public static String title(String string) {
        char[] chars = string.toCharArray();

        List<Character> ls = new ArrayList(chars.length);

        List<Integer> index = new ArrayList<>();
        for (int i = 0; i < chars.length; i++) {
            char c = chars[i];

            if(c>='A' && c<='Z'){
                chars[i] = (char) (c + 32);
                ls.add(chars[i]);
                if(i!=0){
                    index.add(i+index.size());
                }

            }else {
                ls.add(c);
            }
        }



        for (Integer integer : index) {
            ls.add(integer,'_');
        }

        char[] end = new char[ls.size()];
        for (int i = 0; i < ls.size(); i++) {
            end[i] = ls.get(i);
        }

        return new String(end);
    }

    private static void transConstructor(Document document,Node node,Map<String,Node> nodeMap){
        try {
            Element constructorTable = document.body().getElementById("constructor").nextElementSibling();
            Element element = constructorTable.getElementsByTag("strong").get(0);
            //获取注释
            String note = element.parent().nextElementSibling().text();
            node.setNoteEn(note);
            GT g = GT.getInstance();
            note = g.translateText(note,"auto","zh_cn");
            node.setNote(note);


            List<Arg> args = new ArrayList<>();
            node.setArgs(args);
            Map<String, String> fieldType = getStringStringMap(element);
            //获取方法名
            String nodeName = element.text();
            nodeName = StringUtil.replace(nodeName,"(","");
            nodeName = StringUtil.replace(nodeName,")","");
            node.setNodeName(StringUtil.upperFirst(nodeName.trim()));

            if (CollectionUtil.isNotEmpty(fieldType)) {
                for (Map.Entry<String, String> entry : fieldType.entrySet()) {
                    String key = entry.getKey();
                    String value = entry.getValue();
                    Arg arg = getArg(key,value,node.getNodeName());
                    if(!arg.isEmpty()){
                        args.add(arg);
                    }
                }
            }
            nodeMap.put(node.getNodeName(),node);
        }catch (Exception e){
            System.out.println(e.getMessage());
        }

    }

    public static Map<String, String> getStringStringMap(Element element) {
        Map<String, String> fieldType = new HashMap<>();

        //先获取参数数据
        Elements codes = element.getElementsByTag("code");
        if (CollectionUtil.isNotEmpty(codes)) {
            Iterator<Element> codeIterator = codes.iterator();
            //每两个一组
            String field = null;
            int a = 0;
            while (codeIterator.hasNext()) {
                Element code = codeIterator.next();
                if(StringUtil.isNotEmpty(code.text())){
                    if (a % 2 == 1) {
                        fieldType.put(field, code.text());
                    } else {
                        field = code.text();
                    }
                    a++;
                }
                codeIterator.remove();
                code.remove();
            }
        }
        return fieldType;
    }

    private static void transMethod(Document document,Node node,Map<String,Method> methodMap){
        try {
            List<Method> methods = new ArrayList<>();
            node.setMethods(methods);
            Element methodsHead = document.body().getElementById("property-methods");
            if(methodsHead!=null){
                Element table = methodsHead.nextElementSibling();
                Elements tbodys = table.getElementsByTag("tbody");
                if(tbodys!=null){
                    Element tbody = tbodys.first();
                    if(tbody!=null){
                        //按tr分组
                        Elements trs = tbody.getElementsByTag("tr");
                        for (Element tr : trs){
                            Method method = new Method();
                            methods.add(method);
                            Element nameEle = tr.child(0).getElementsByTag("a").first();
                            String name = StringUtil.upperFirst(nameEle.text().trim());
                            method.setName(name);
                            Map<String, String> fieldType = getStringStringMap(tr);
                            if (CollectionUtil.isNotEmpty(fieldType)) {
                                List<Arg> args = new ArrayList<>();
                                method.setArgs(args);
                                for (Map.Entry<String, String> entry : fieldType.entrySet()) {
                                    String key = entry.getKey();
                                    String value = entry.getValue();
                                    Arg arg = getArg(key,value,node.getNodeName());
                                    if(!arg.isEmpty()){
                                        args.add(arg);
                                    }
                                }
                            }
                            //获取注释
                            String note = tr.child(1).text();
                            method.setNoteEn(note);
                            GT g = GT.getInstance();
                            note = g.translateText(note,"auto","zh_cn");
                            method.setNote(note);

                            if(!method.isEmpty()){
                                methodMap.put(name,method);
                            }
                        }
                    }
                }
            }
        }catch (Exception e){
            System.out.println(e.getMessage());
        }

    }

    public static void linkNode(Document document,Node node){
        List<String> linkNodes = new ArrayList<>();
        node.setLinkNodes(linkNodes);
        Element methodsHead = document.body().getElementById("chaining-methods");
        if (methodsHead!=null) {
            Element pTag = methodsHead.nextElementSibling();
            if(pTag!=null){
                Elements aTags = pTag.getElementsByTag("a");
                for (Element aTag : aTags) {
                    linkNodes.add(aTag.text());
                }
            }
        }
    }

    public static Arg getArg(String key,String value,String name){
        Arg arg = new Arg();
        if(StringUtil.containsIgnoreCase(value,"...")){
            arg.setIsList(1);
        }
        if("value".equals(key)&&StringUtil.containsIgnoreCase(value,"LambdaNode")){
            arg.setName("condition");
            arg.setType("String");
            arg.setConvertType("LambdaArg");
        }else if(StringUtil.containsIgnoreCase(value,"time.Duration")){
            arg.setTimeArg(1);
        }else if(StringUtil.containsIgnoreCase(value,"interface")){
            if("value".equals(key)){
                arg.setName(name);
            }else {
                arg.setName(key);
            }
            arg.setType("Object");
            arg.setConvertType("OriginalArg");
        }else if(StringUtil.containsIgnoreCase(value,"string")){
            if("value".equals(key)){
                arg.setName(name);
            }else {
                arg.setName(key);
            }
            arg.setType("String");
            arg.setConvertType("SingleQuotesArg");
        }else if(StringUtil.containsIgnoreCase(value,"float64")){
            if("value".equals(key)){
                arg.setName(name);
            }else {
                arg.setName(key);
            }
            arg.setType("double");
            arg.setConvertType("OriginalArg");
        }else if(StringUtil.containsIgnoreCase(value,"int64")){
            if("value".equals(key)){
                arg.setName(name);
            }else {
                arg.setName(key);
            }
            arg.setType("long");
            arg.setConvertType("OriginalArg");
        }else if(StringUtil.containsIgnoreCase(value,"bool")){
            if("value".equals(key)){
                arg.setName(name);
            }else {
                arg.setName(key);
            }
            arg.setType("boolean");
            arg.setConvertType("OriginalArg");
        }else if(StringUtil.containsIgnoreCase(value,"Node")){
            if("value".equals(key)){
                arg.setName(name);
            }else {
                arg.setName(key);
            }
            arg.setType("Node");
            arg.setConvertType("OriginalArg");
        }
        return arg;
    }
}
